/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package unilearn.bo.servlet;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import unilearn.bo.AssignmentManagement;
import unilearn.bo.SubmissionManagement;
import unilearn.util.web.Download;
import unilearn.vo.Assignment;
import unilearn.vo.Submission;

/**
 *
 * @author Yat
 */
public class SubmissionUploadServlet extends HttpServlet {

    private String tempPath;
    private int maxSize;
    private SubmissionManagement submMgt;
    private AssignmentManagement assignMgt;

    public void init() throws ServletException {
        try {
            tempPath = this.getServletConfig().getInitParameter("tempPath");
            checkDir(tempPath);
            maxSize = Integer.parseInt(this.getServletConfig().getInitParameter("maxSize"));
            WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
            submMgt = (SubmissionManagement) context.getBean("submMgt");
            assignMgt = (AssignmentManagement) context.getBean("assignMgt");
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String page = null;

        try {
            // get form data
//            System.out.println("get form data");
            Map<String, Object> form = getForm(request);
//            for (String k : form.keySet()) {
//                System.out.println("k: " + k + ", v: " + form.get(k));
//            }
            if (!form.containsKey("assignId")) {
                throw new ServletException("Could not find assignment id.");
            }
            Assignment assign = assignMgt.getAssignment(new Integer((String) form.get("assignId")));
            if (assign == null) {
                throw new ServletException("Could not find assignment.");
            }

            if (assign.getDueDate().after(new Date())) {
                throw new Exception("Submission date is expired.");
            }

//            System.out.println("check form data");
            if ((!form.containsKey("autorId")) && (!form.containsKey("assignFile"))) {
                page = null;
                throw new Exception("Could not find autorId / assignFile.");
            }

//            System.out.println("create submission");
            Submission subm = new Submission();
            subm.setAssignmentId(assign.getId());
            subm.setSubjectCode(assign.getSubjectCode());

            if ((form.containsKey("autorId")) && (!form.get("autorId").equals(""))) {
                subm.setAutorId(new Integer(((String) form.get("autorId"))));
            }

            Map<String, byte[]> file = (Map<String, byte[]>) form.get("assignFile");
            String fileName = null;
            byte[] fileBytes = null;
            for (String k : file.keySet()) {
                fileName = k;
                fileBytes = file.get(k);
            }

//            System.out.println("[SubmissionUploadServlet]createSubmission");//***
            subm = submMgt.createSubmission(subm, fileName, fileBytes);
//            System.out.println("[SubmissionUploadServlet]getReceptFile");//***
            byte[] recBytes = submMgt.getReceptFile(subm);
//            System.out.println("[SubmissionUploadServlet]doDownload");//***
            Download.doDownload(response, "recept.pdf", recBytes);
        } catch (Exception e) {
            page = null;
            System.out.println(e.toString());
        } finally {
            if (page == null) {
                //front back
                response.sendRedirect(request.getHeader("referer"));
            }
        }
    }

    private Map<String, Object> getForm(HttpServletRequest request) throws ServletException, IOException {
        Map<String, Object> form = new HashMap();
        try {
            if (!ServletFileUpload.isMultipartContent(request)) {
                throw new ServletException("Form enctype must be multipart/form-data");
            }

            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold((1 * 1024 * 1024));
            factory.setRepository(new File(tempPath));

            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setSizeMax((maxSize * 1024 * 1024));

            System.out.println("[getForm] get items");
            List<FileItem> items = upload.parseRequest(request);
            if ((items == null) || (items.isEmpty())) {
                throw new ServletException("Could not find form data.");
            }

            System.out.println("[getForm] foreach items");
            for (FileItem item : items) {
                if (item.isFormField()) {
                    System.out.println("[getForm] field: " + item.getFieldName());
                    form.put(item.getFieldName(), item.getString());
                } else {
                    System.out.println("[getForm] file: " + item.getFieldName());
                    form.put(item.getFieldName(), setFormFile(item));
                }
            }

            return form;
        } catch (ServletException se) {
            throw se;
        } catch (IOException ioe) {
            throw ioe;
        } catch (Exception e) {
            System.out.println(getClass().getName() + "[getForm]\n" + e.toString());
        } finally {
        }
        return null;
    }

    private Map<String, byte[]> setFormFile(FileItem item) throws ServletException, IOException {
        if (!item.getFieldName().equals("assignFile")) {
            return null;
        }

        String fileName = item.getName();
        byte[] fileBytes = null;

        BufferedInputStream bis = null;

        try {
            InputStream is = item.getInputStream();
            if (is == null) {
                throw new IOException("InputStream is null.");
            }

            bis = new BufferedInputStream(is);
            fileBytes = new byte[bis.available()];
            bis.read(fileBytes);

        } catch (IOException ioe) {
            throw ioe;
        } catch (Exception e) {
            System.out.println(getClass().getName() + "[setFormFile]\n " + e.toString());
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
            } catch (Exception e) {
            }
        }

        Map<String, byte[]> file = new HashMap();
        file.put(fileName, fileBytes);

        return file;
    }

    private void checkDir(String path) throws IOException {
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
